<script setup lang="ts">
import { ref } from "vue";
import { LPolyline, LCircle, LMarker } from "@vue-leaflet/vue-leaflet";
import { useMapStore } from "@/store";
import { MAP_ACTION } from "@/views/pipe-network/constants";
import {deletePolyline, queryPointsPro, queryPolylines, queryPolylinesPro} from "@/api/pipe";
import {
  getNearestPointOnLine,
  nearestPointOnLine,
  splitLineByPoint,
} from "@/views/pipe-network/utils";
import { useLocalStore } from "@/views/pipe-network/store";
const props = defineProps({
  deviceCategoryList: Array<any>,
  map: Object,
});
const { L }: any = window;
const { map }: any = toRefs(props);
const dialogVisible = ref<boolean | number>(false);
const polylineListRef = ref([]);
const pointListRef = ref([]);
const circleMarkerPositionRef = ref();
const activePolylineRef = ref();
const timestampRef = ref(-1);
const radius = ref(5);
const mapStore = useMapStore();
const { mapAction } = storeToRefs(mapStore);
const localStore = useLocalStore();
const { updateLineAPICount } = storeToRefs(localStore);
let timer: any;
const onClick = (e: any) => {
  const isAddPointOnLineAction =
    mapAction.value === MAP_ACTION.ADD_POINT_ONLINE;
  const isPointDevideLineAction =
    mapAction.value === MAP_ACTION.DEVIDE_LINE_WITH_POINT;
  const isModifyInfoAction = mapAction.value === MAP_ACTION.EDIT;
  const { lineId } = e.target.options.attribution;
  const obj = polylineListRef.value.find((item: any) => item.lineId === lineId);
  if (isAddPointOnLineAction || isPointDevideLineAction) {
    const { lat, lng } = e.latlng;
    const lines = activePolylineRef.value.latlngs.map((item) => {
      const { lat, lng } = item;
      return [lng, lat];
    });
    const snnapped = getNearestPointOnLine([lng, lat], lines);
    const {
      geometry: { coordinates },
      properties: { dist },
    } = snnapped;
    if (dist < 1 && isAddPointOnLineAction) {
      mapStore.setAddedPipePointOnLine({
        lat: coordinates[1],
        lng: coordinates[0],
      });
    }
    if (dist < 1 && isPointDevideLineAction) {
      mapStore.setPointDevideLine({
        point: {
          lat: coordinates[1],
          lng: coordinates[0],
        },
        lines: []
      });
    }
    if (isPointDevideLineAction) {
      const split = splitLineByPoint(lines, coordinates);
      const { lineId } = activePolylineRef.value;
      const object = polylineListRef.value.find(
        (item) => item.lineId === lineId
      );
      if (object) {
        const clone = { ...object };
        delete clone.startPoint;
        delete clone.coordinates;
        delete clone.geom;
        const newLines = split.features.map((item, index) => {
          const obj = { ...clone };
          obj.jsonGeom = JSON.stringify(item);
          if (index === 1) {
            delete obj.lineId;
          }
          return obj;
        });
        mapStore.setSplitLines(newLines);
      }
    }
  }
  if (isModifyInfoAction) {
    if (obj) {
      mapStore.setEditingPipeLine(obj);
    }
  }
  if (!mapAction.value && obj) {
    localStore.setSelectedFeature(obj);
  }
};
const onHover = (e: any) => {
  const isConnectionTwoPointsAction =
    mapAction.value === MAP_ACTION.ADD_POINT_ONLINE;
  const isPointDevideLineAction =
    mapAction.value === MAP_ACTION.DEVIDE_LINE_WITH_POINT;
  if (isConnectionTwoPointsAction || isPointDevideLineAction) {
    circleMarkerPositionRef.value = e.latlng;
    activePolylineRef.value = {
      latlngs: e.target.getLatLngs(),
      lineId: e.target.options.attribution.lineId,
    };
    timer && clearTimeout(timer);
    timestampRef.value = new Date().getTime();
  }
};
const onUnHover = () => {
  const isConnectionTwoPointsAction =
    mapAction.value === MAP_ACTION.ADD_POINT_ONLINE;
  const isPointDevideLineAction =
    mapAction.value === MAP_ACTION.DEVIDE_LINE_WITH_POINT;
  if (isConnectionTwoPointsAction || isPointDevideLineAction) {
    let _lastTimestamp = timestampRef.value;
    timer = setTimeout(() => {
      if (_lastTimestamp >= timestampRef.value) {
        activePolylineRef.value = null;
        circleMarkerPositionRef.value = null;
        timer = null;
      }
    }, 1000);
  }
};
const isSameLatlng = (latlngA, latlngB) => {
  return latlngA.lat === latlngB.lat && latlngA.lng === latlngB.lng;
};
const getWeight = (lineId) => {
  if (!activePolylineRef.value) {
    return 2;
  } else {
    return 6;
  }
};
const onZoom = (e: any) => {
  const zoom = e.target.getZoom();
  if (zoom > 17) {
    radius.value = 2;
  } else if (zoom > 16) {
    radius.value = 5;
  } else if (zoom > 14) {
    radius.value = 10;
  } else {
    radius.value = 15;
  }
};
const onMouseMove = (e: any) => {
  const isConnectionTwoPointsAction =
    mapAction.value === MAP_ACTION.ADD_POINT_ONLINE;
  const isPointDevideLineAction =
    mapAction.value === MAP_ACTION.DEVIDE_LINE_WITH_POINT;
  if (
    (isConnectionTwoPointsAction || isPointDevideLineAction) &&
    activePolylineRef.value
  ) {
    circleMarkerPositionRef.value = e.latlng;
  }
};
const getColor = (classId: string) => {
  return props.deviceCategoryList?.getLineColor(classId);
};
const getAllLines = () =>
  queryPolylinesPro({ pageSize: 100000, pageIndex: 1 }).then(
    ({ data, errors, succeeded }: any) => {
      if (succeeded && Array.isArray(data?.items)) {
        polylineListRef.value = data.items
          .filter((item: any) => item.jsonGeom)
          .map((item: any) => {
            const { coordinates } = JSON.parse(item.jsonGeom);
            const [lng, lat] = coordinates[0];
            const [endLng, endLat] = coordinates[coordinates.length - 1];
            return {
              ...item,
              coordinates: coordinates.map((item: any) => [item[1], item[0]]),
              startPoint: [lat, lng],
              endPoint: [endLat, endLng],
              color: getColor(item.classId),
            };
          });
      }
    }
  );
const getAllPoints = () =>
    queryPointsPro({ pageSize: 100000, pageIndex: 1 }).then(
        ({ data, errors, succeeded }: any) => {
          if (succeeded && Array.isArray(data?.items)) {
            pointListRef.value = data.items
                .filter((item: any) => item.jsonGeom)
                .map((item: any) => {
                  const [lng, lat] = JSON.parse(item.jsonGeom).coordinates;
                  return {
                    ...item,
                    latlng: [lat, lng],
                  };
                });
          }
        }
    );
const _deleteLine = (lineId: number) => {
  deletePolyline(lineId).then((res: any) => {
    if (res.succeeded) {
      ElMessage("删除成功！");
      getAllLines();
    } else {
      ElMessage("删除失败！");
    }
  });
};
onMounted(() => {
  getAllLines();
  getAllPoints();
});
onUnmounted(() => {
  if (map?.value) {
    map.value.off("zoom", onZoom).off("mousemove", onMouseMove);
  }
});
watchEffect(() => {
  map?.value && map.value.on("zoom", onZoom).on("mousemove", onMouseMove);
});
watchEffect(() => {
  if (updateLineAPICount.value >= 0) {
    getAllLines();
  }
});
</script>

<template v-if="positionRef">
  <LCircle
    v-if="circleMarkerPositionRef"
    :lat-lng="circleMarkerPositionRef"
    color="red"
    :radius="radis"
    weight="1"
    fillOpacity="1"
    @click="onClick"
    @mouseout="onUnHover"
  />
  <template v-if="!activePolylineRef">
    <LPolyline
      :key="lineId"
      v-for="{ coordinates, lineId, color } in polylineListRef"
      :lat-lngs="coordinates"
      :weight="3"
      :color="color"
      :attribution="{ lineId }"
      @click="onClick"
      @mouseover="onHover"
    />
  </template>
  <LPolyline
    v-if="activePolylineRef"
    :lat-lngs="activePolylineRef.latlngs"
    :weight="8"
    :attribution="{ lineId: activePolylineRef.lineId }"
    @click="onClick"
    color="yellow"
    @mouseout="onUnHover"
  />

  <template v-if="mapAction === MAP_ACTION.ADD_PIPELINE">
    <LCircle
      v-for="{ startPoint, lineId } in polylineListRef"
      :key="lineId"
      :lat-lng="startPoint"
      :radius="20"
      color="red"
      fill-color="white"
      :fillOpacity="0.3"
      :pacity="0.3"
      @click="
        (e: any) =>
          mapStore.setStartPointInfo({
            original: e.target.getLatLng(),
            latlng: e.latlng,
          })
      "
      @mouseover="
        (e: any) => {
          e.target.getElement().style.fillOpacity = 1;
          e.target.getElement().style.opacity = 1;
        }
      "
      @mouseout="
        (e: any) => {
          e.target.getElement().style.fillOpacity = 0.3;
          e.target.getElement().style.opacity = 0.3;
        }
      "
    />
    <LCircle
      v-for="{ endPoint, lineId } in polylineListRef"
      :key="lineId"
      :lat-lng="endPoint"
      :radius="20"
      color="red"
      fill-color="white"
      :fillOpacity="0.3"
      :pacity="0.3"
      @click="
        (e: any) =>
          mapStore.setStartPointInfo({
            original: e.target.getLatLng(),
            latlng: e.latlng,
          })
      "
      @mouseover="
        (e: any) => {
          e.target.getElement().style.fillOpacity = 1;
          e.target.getElement().style.opacity = 1;
        }
      "
      @mouseout="
        (e: any) => {
          e.target.getElement().style.fillOpacity = 0.3;
          e.target.getElement().style.opacity = 0.3;
        }
      "
    />
    <LCircle
        v-for="{ latlng, pointId, depth } in pointListRef"
        :key="pointId"
        :lat-lng="latlng"
        :radius="20"
        color="red"
        fill-color="white"
        :fillOpacity="0.3"
        :pacity="0.3"
        @click="
        (e: any) =>
          mapStore.setStartPointInfo({
            original: e.target.getLatLng(),
            latlng: e.latlng,
            depth
          })
      "
        @mouseover="
        (e: any) => {
          e.target.getElement().style.fillOpacity = 1;
          e.target.getElement().style.opacity = 1;
        }
      "
        @mouseout="
        (e: any) => {
          e.target.getElement().style.fillOpacity = 0.3;
          e.target.getElement().style.opacity = 0.3;
        }
      "
    />
  </template>
  <template v-if="mapAction === MAP_ACTION.DELETE">
    <LMarker
      v-for="{ startPoint, lineId } in polylineListRef"
      :lat-lng="startPoint"
      :key="lineId"
      :icon="
        L.divIcon({
          html: `<div style=&quot;width: 13px;height: 13px;cursor: pointer; position: relative; top: -7px; left: 17px; border: 1px solid;transform: scale(1.1);&quot;>
              <svg viewBox=&quot;0 0 40 40&quot; style=&quot;position: relative;left: 0px; top: -4px;&quot;>
                  <path stroke=&quot;#FF0000&quot; stroke-width=&quot;3&quot; d=&quot;M 10,10 L 30,30 M 30,10 L 10,30&quot; />
                  </svg>
              </div>`,
          className: 'abc',
        })
      "
      @click="dialogVisible = lineId"
    />
  </template>
  <el-dialog v-model="dialogVisible" title="提示" width="400">
    <span class="dialog-content">确认删除吗？</span>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button
          type="primary"
          @click="
            _deleteLine(dialogVisible);
            dialogVisible = false;
          "
        >
          确认
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<style scoped lang="scss">
.dialog-content {
  display: inline-block;
  padding: 20px 20px 0;
}

.dialog-footer {
  padding: 20px;
}
</style>
